home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cmln0586.arc / POLYGON1.LTG < prev   
Text File  |  1986-04-06  |  10KB  |  285 lines

  1. #include <stdio.h>
  2. /*                                       */
  3. /*    Polygon Fill Routine - POLYHATCH                   */
  4. /*                                       */
  5. /*    This routine is a Raster Scan Fill which will fill (or hatch)       */
  6. /*    the object reperesented by the input data. The following       */
  7. /*    describes the input date:                       */
  8. /*                                       */
  9. /*    COLOR       - The current fill color (or pattern) to be used.       */
  10. /*    POINTS       - The co-ordinate pairs for the object (See DTABLE).    */
  11. /*    NUM_POINTS - The number of coordinate points stored in POINTS.       */
  12. /*    CROSSHATCH - Global Flag for Solid/Crosshatch Fill Decision       */
  13. /*                                       */
  14. #define ROUND_OFF   0.001    /* set comparison tolerence for horz lines */
  15. #define LINE_WIDTH   10.0    /* Width of scan line in coordinate units  */
  16. #define MAX_EDGE     1000    /* Maximum number of edges in EDGE_TBL       */
  17. #define MAX_PATTERN    16    /* Maximum number of different crosshatchs */
  18.  
  19. #define INTER1      8*LINE_WIDTH    /* Interval between lines for crosshatch   */
  20. #define INTER2      2*LINE_WIDTH    /* Interval between D_SCAN Line pairs       */
  21.  
  22. extern    int    crosshatch;    /* TRUE = Crosshatch;  FALSE = Solid Fill  */
  23.  
  24. #define PI    3.1415927            /* define a value for pi   */
  25. #define max( A, B )  ((A) > (B) ? (A) : (B))    /* define a MAX function   */
  26. #define min( A, B )  ((A) < (B) ? (A) : (B))    /* define a MIN function   */
  27.  
  28. struct DTABLE {         /* declare structure for data table       */
  29.   int x;            /* data table x value               */
  30.   int y;            /* data table y value               */
  31.   };
  32.  
  33. struct HATCHTABLE {        /* Define Control Table for Cross Hatchs   */
  34.    int df_flag;         /* Flag for Double Line Fill           */
  35.    int ds_flag;         /* Flag for Fouble Scan Fill           */
  36.    float angle1;        /* Pass 1 Rotation Fill Angle           */
  37.    float angle2;        /* Pass 2 Rotation Fill Angle (if needed)  */
  38.    };
  39.  
  40. struct edge_rec {        /* define an edge table entry record       */
  41.    float ymin;            /* Minimum Y value for current line vector */
  42.    float ymax;            /* Maximum Y value for current line vector */
  43.    float deltax;        /* Slope of the current line vector       */
  44.    float xval;            /* X Intercept of the current line vector  */
  45.    };
  46.  
  47. struct HATCHTABLE htable[] = {        /* Fill Pattern Definition Table   */
  48. /* Double   Double    1st      2nd           Description    Pattern #  */
  49. /*  Fill     Scan    Angle    Angle                in Fig. 2  */
  50.    FALSE,   FALSE,     0.0,    0.0,    /* No Fill In This Case       1    */
  51.    FALSE,   FALSE,     0.0,    0.0,    /* Rotate 0 Deg.          2    */
  52.    FALSE,   FALSE,   -PI/4,    0.0,    /* Rotate -45 Deg.          3    */
  53.     TRUE,   FALSE,     0.0,   PI/2,    /* Rotate 0 and 90 Deg.       4    */
  54.    FALSE,   FALSE,    PI/4,    0.0,    /* Rotate 45 Deg.          5    */
  55.     TRUE,   FALSE,    PI/4,  -PI/4,    /* Rotate ± 45 Deg.          6    */
  56.    FALSE,   FALSE,    PI/2,    0.0,    /* Rotate 90 Deg.          7    */
  57.     TRUE,   FALSE,    PI/9,  -PI/9,    /* Rotate ± 20 Deg.          8    */
  58.     TRUE,    TRUE,   -PI/4,   PI/4,    /* Double Fill, ± 45 Deg.     9    */
  59.     TRUE,    TRUE,     0.0,   PI/2,    /* Double Fill, 0 & 90 Deg.  10    */
  60.    FALSE,   FALSE,    PI/9,    0.0,    /* Rotate 20 Deg.         11    */
  61.    FALSE,    TRUE,    PI/2,    0.0,    /* Double Scan, 90 Deg.      12    */
  62.    FALSE,   FALSE,   -PI/9,    0.0,    /* Rotate -20 Deg.         13    */
  63.    FALSE,    TRUE,    PI/4,    0.0,    /* Double Scan, 45 Deg.      14    */
  64.    FALSE,    TRUE,   -PI/4,    0.0,    /* Double Scan, -45 Deg.     15    */
  65.    FALSE,    TRUE,     0.0,    0.0    /* Double Scan, 0 Deg.         16    */
  66.  };
  67.  
  68. struct    edge_rec  edge_tbl[ MAX_EDGE ];  /* Define table for edge storage  */
  69. int    num_edges;        /* Number of edges in edge table       */
  70. float    scan_line;        /* Location of current scan line to fill   */
  71. int    scan_dec;        /* Distance between lines in fill       */
  72. float    r_angle;        /* Angle of current rotation           */
  73. int    d_scan, d_fill;     /* Flags to control fill pattern to be used*/
  74. int    start_edge, end_edge;    /* Starting and ending edge of fill line   */
  75.  
  76. float fabs();            /* Declare library function for module       */
  77.  
  78. polyhatch( color, points, num_points )
  79. int color;
  80. struct DTABLE *points;
  81. int num_points;
  82. {
  83.    int     i, p_num;
  84.  
  85.    polyline( color, points, num_points ); /* draw a border around polygon  */
  86.  
  87.    d_fill = d_scan = FALSE;        /* assume no double scans or fills */
  88.    r_angle = 0.0;            /* assume horizontal fill       */
  89.    scan_dec = LINE_WIDTH;        /* assume standard line width       */
  90.  
  91.    if( crosshatch ){
  92.      p_num    = color % 16;
  93.      d_fill   = htable[p_num].df_flag;    /* Set Double Fill Flag        */
  94.      d_scan   = htable[p_num].ds_flag;    /* Set Double Scan Flag        */
  95.      r_angle  = htable[p_num].angle1;    /* Set 1st Rotation Angle       */
  96.      scan_dec = 10 * LINE_WIDTH;    /* Set line spacing 1st line       */
  97.      }
  98.  
  99.    do_fill( points, num_points );
  100.  
  101.    if ( d_fill ) {
  102.       for( i=0; i<num_points; ++i )    /* Rotate data back from last pass */
  103.     rotate( -r_angle, &points[i].x, &points[i].y );
  104.  
  105.       r_angle = htable[p_num].angle2;    /* set second fill angle       */
  106.       scan_dec = 10 * LINE_WIDTH;    /* reset 1st line spacing       */
  107.       do_fill( points, num_points );
  108.    }
  109. }
  110.  
  111. /*    DO_FILL: Draw in one pass of the raster scan line fill              */
  112.  
  113. do_fill( data, count )
  114. struct DTABLE *data;
  115. int   count;
  116. {
  117.   int      i;
  118.   int      dsi_flag = FALSE;    /* Double scan interval flag for D_SCAN      */
  119.  
  120.   for( i=0; i<count; ++i )    /* rotate data to scan angle for this pass   */
  121.     rotate( r_angle, &data[i].x, &data[i].y );
  122.  
  123.   build_table( data, count );            /* build edge table for fill */
  124.   start_edge = end_edge = 0;            /* initialize counters         */
  125.   scan_line = edge_tbl[0].ymax - scan_dec;    /* determine 1st scan line Y */
  126.   include_edge();                /* calculate X intercepts    */
  127.   update_table();                /* re-order table by X value */
  128.   while( start_edge < end_edge ){        /* Scan Line Loop         */
  129.     fill_line();                /* draw current scan line    */
  130.     if( d_scan ){                /* change scan_dec for D_SCAN*/
  131.       scan_dec = dsi_flag ? INTER1 : INTER2;    /* set D_SCAN interval         */
  132.       dsi_flag = !dsi_flag;            /* toggle interval flag      */
  133.       }
  134.     scan_line -= scan_dec;            /* update coord of scan line */
  135.     include_edge();                /* calculate X intercepts    */
  136.     update_table();                /* re-order table by X value */
  137.     }
  138. }
  139.  
  140. /*    Build the edge table from the input data coordinate pairs.         */
  141.  
  142. build_table( data, count )
  143. struct DTABLE *data;
  144. int    count;
  145. {
  146.   float  x1, x2, y1, y2, ymx;
  147.   int i, j, k;
  148.  
  149.   num_edges = 0;
  150.   x1 = (float)data[0].x;
  151.   y1 = (float)data[0].y + 0.5;
  152.  
  153.   for( k=1 ; k<count ; ++k ){
  154.     i = k % (count-1);
  155.     x2 = (float)data[i].x;
  156.     y2 = (float)data[i].y + 0.5;
  157.     if( fabs(y1 - y2) < ROUND_OFF ) x1 = x2;    /* line is essentually horz */
  158.     else {
  159.       ymx = max( y1, y2 );
  160.       j = num_edges - 1;
  161.       while( (edge_tbl[j].ymax < ymx) && (j > -1) ){
  162.      edge_tbl[j+1].ymax   = edge_tbl[j].ymax;
  163.      edge_tbl[j+1].ymin   = edge_tbl[j].ymin;
  164.      edge_tbl[j+1].deltax = edge_tbl[j].deltax;
  165.      edge_tbl[j+1].xval   = edge_tbl[j].xval;
  166.      --j;
  167.      }
  168.       ++j;
  169.       ++num_edges;
  170.       edge_tbl[j].ymax     = ymx;
  171.       edge_tbl[j].ymin     = min( y1, y2 );
  172.       edge_tbl[j].deltax = (x2 - x1)/(y2 - y1);
  173.       edge_tbl[j].xval     = ( y1 < y2 ) ? x2 : x1;
  174.       x1 = x2;
  175.       y1 = y2;
  176.       }
  177.   }
  178. }
  179.  
  180. /*    Calculate the X interception point of all lines which have a       */
  181. /*    ymax less than or equal to the y value of the current scan line.   */
  182.  
  183. include_edge()
  184. {
  185.   int i;
  186.  
  187.   i = end_edge;
  188.   while( (i++ < num_edges) && (edge_tbl[end_edge+1].ymax >= scan_line) ){
  189.     edge_tbl[end_edge+1].xval = edge_tbl[end_edge+1].xval +
  190.           (edge_tbl[end_edge+1].deltax * (scan_dec + scan_line -
  191.                   edge_tbl[end_edge+1].ymax));
  192.     end_edge++;
  193.   }
  194. }
  195.  
  196. update_table()
  197. {
  198.   int i, j, k, first_edge;
  199.   float temp, deltay;
  200.  
  201.   first_edge = start_edge;
  202.   for( i=first_edge; i<end_edge; ++i ){
  203.     if( edge_tbl[i].ymin < scan_line ){
  204.       deltay = fabs( edge_tbl[i].ymax - edge_tbl[i].ymin );
  205.       deltay = min( deltay, scan_dec );
  206.       edge_tbl[i].xval = edge_tbl[i].xval - (edge_tbl[i].deltax * deltay);
  207.       k = i;
  208.       while( (k > start_edge) && (edge_tbl[k].xval < edge_tbl[k-1].xval ) ){
  209.     temp = edge_tbl[k].ymin;
  210.     edge_tbl[k].ymin = edge_tbl[k-1].ymin;
  211.     edge_tbl[k-1].ymin = temp;
  212.     temp = edge_tbl[k].deltax;
  213.     edge_tbl[k].deltax = edge_tbl[k-1].deltax;
  214.     edge_tbl[k-1].deltax = temp;
  215.     temp = edge_tbl[k].xval;
  216.     edge_tbl[k].xval = edge_tbl[k-1].xval;
  217.     edge_tbl[k-1].xval = temp;
  218.     k--;
  219.       }
  220.     }
  221.     else {
  222.       start_edge++;
  223.       if (start_edge <= i) {
  224.     for( j=i; i>start_edge; --i ){
  225.       edge_tbl[j].ymin = edge_tbl[j-1].ymin;
  226.       edge_tbl[j].xval = edge_tbl[j-1].xval;
  227.       edge_tbl[j].deltax = edge_tbl[j-1].deltax;
  228.     }
  229.       }
  230.     }
  231.   }
  232. }
  233.  
  234. /*    Draw the line segments of the current scan line to output device.    */
  235.  
  236. fill_line()
  237. {
  238.   static int line_state;    /* Direction to draw current fill line       */
  239.   int i, k, j = 1;
  240.   int xtmp, ytmp, inc, inc2;
  241.  
  242.   i = end_edge - start_edge;
  243.   k = line_state ? end_edge : start_edge;
  244.   inc2 = 2 * (inc = line_state ? -1 : 1);
  245.   while( j <= i ){
  246.      xtmp = (int)(edge_tbl[k].xval + 0.5);
  247.      ytmp = (int)scan_line;
  248.      rotate( -r_angle, &xtmp, &ytmp );
  249.      move_abs( xtmp, ytmp );
  250.      xtmp = (int)(edge_tbl[k+inc].xval + 0.5);
  251.      ytmp = (int)scan_line;
  252.      rotate( -r_angle, &xtmp, &ytmp );
  253.      line_abs( xtmp, ytmp );
  254.      k += inc2; j += 2;
  255.   }
  256.  
  257.   line_state = !line_state;              /* toggle line state    */
  258. }
  259.  
  260. /*    ROTATE: Rotate the X-Y Coordinate pair by the preset angle    */
  261.  
  262. rotate( angle, x, y )
  263. float angle;
  264. int *x, *y;
  265. {
  266.   float   sinx, siny, cosx, cosy;
  267.   float   sin(), cos();
  268.   static  float  p_angle = 0.0, p_sin = 0.0, p_cos = 1.0;
  269.   float   xtemp, ytemp;
  270.  
  271.   if( angle==0.0 ) return;    /* no rotation required for 0.0 degrees    */
  272.  
  273.   if( angle != p_angle ){    /* angle has changed, calculate new values */
  274.     p_sin = sin( angle );
  275.     p_cos = cos( angle );
  276.     p_angle = angle;
  277.     }
  278.  
  279.   sinx = p_sin * (float)(*x);        cosx = p_cos * (float)(*x);
  280.   siny = p_sin * (float)(*y);        cosy = p_cos * (float)(*y);
  281.  
  282.   *x = (int)( cosx - siny );        *y = (int)( cosy + sinx );
  283.  
  284. }
  285.